package Java7_Concurrency_Cookbook.thread_synchronized_helper.phaser;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 * @author lixiangke
 * @date 2017/11/14
 */
public class FileSearch implements Runnable {
    private String initPath;
    private String end;
    private List<String> results;
    private Phaser phaser;

    public FileSearch(String initPath, String end, Phaser phaser) {
        this.initPath = initPath;
        this.end = end;
        this.phaser = phaser;
        this.results = new ArrayList<>();
    }

    @Override
    public void run() {
        // 确保三个线程同时启动
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: Starting. \n", Thread.currentThread().getName());
        File file = new File(initPath);
        if (file.isDirectory()) {
            directoryProcess(file);
        }
        if (!checkResults()) {
            return;
        }
        filterResults();
        if (!checkResults()) {
            return;
        }
        showInfo();
        phaser.arriveAndDeregister();
        System.out.printf("%s: Work completed. \n", Thread.currentThread().getName());
    }

    private void directoryProcess(File file) {
        File list[] = file.listFiles();
        if (list != null) {
            for (int i = 0; i < list.length; i++) {
                if (list[i].isDirectory()) {
                    directoryProcess(list[i]);
                } else {
                    fileProcess(list[i]);
                }
            }
        }
    }

    private void fileProcess(File file) {
        if (file.getName().endsWith(end)) {
            results.add(file.getAbsolutePath());
        }
    }

    private void filterResults() {
        List<String> newResults = new ArrayList<>();
        long actualDate = new Date().getTime();
        for (int i = 0; i < results.size(); i++) {
            File file = new File(results.get(i));
            long fileDate = file.lastModified();
            if (actualDate - fileDate < TimeUnit.MILLISECONDS
                    .convert(1, TimeUnit.DAYS)) {
                newResults.add(results.get(i));
            }
        }
        results = newResults;
    }

    private boolean checkResults() {
        String tName = Thread.currentThread().getName();
        if (results.isEmpty()) {
            System.out.println(tName + " : Phase " + phaser.getPhase() + " : 0 results.");
            System.out.println(tName + " : Phase " + phaser.getPhase() + " : End.");
            // 通知 phaser 对象参与同步的线程少了一个,
            // 因而 phaser 对象在开始下一阶段时不会等待这个线程了
            phaser.arriveAndDeregister();
            return false;
        } else {
            System.out.println(tName + " : Phase " + phaser.getPhase() + " : " + results.size() + " results.");
            // phaser 对象将减 1, 并把这个线程置于休眠状态, 直到所有其它线程完成这个阶段
            phaser.arriveAndAwaitAdvance();
            return true;
        }
    }

    private void showInfo() {
        for (int i = 0; i < results.size(); i++) {
            File file = new File(results.get(i));
            String tName = Thread.currentThread().getName();
            System.out.println(tName + " : " + file.getAbsolutePath());
        }
        phaser.arriveAndAwaitAdvance();
    }

}
